﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using LimaLims.Application.Service.Base.Dto;
using LimaLims.Application.Service.Equipment.Dto;
using LimaLims.Application.Service.Sys;
using LimaLims.Core;
using LimaLims.Core.Entity.Equipment;
using LimaLims.Core.Enum;
using LimaLims.Core.Util;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq;

namespace LimaLims.Application.Service.Equipment
{
    /// <summary>
    /// 设备仪器服务
    /// </summary>
    [ApiDescriptionSettings(Name = "EquipmentInfo", Order = 151)]
    [Route("api")]
    public class EquipmentInfoService : IEquipmentInfoService, IDynamicApiController, ITransient
    {
        private readonly IRepository<EquipmentInfo> _equipmentRep;  // 设备仪器表仓储
        private readonly IGenerateCodeUtilService _generateCodeUtilService;//编码规则

        public EquipmentInfoService(IRepository<EquipmentInfo> equipmentRep, IGenerateCodeUtilService generateCode)
        {
            _equipmentRep = equipmentRep;
            _generateCodeUtilService = generateCode;
        }

        /// <summary>
        /// 新增
        /// </summary>
        [HttpPost("equipmentInfo/add")]
        public async Task Add(AddEquipmentInfoInput input)
        {
            var isExist = await _equipmentRep.DetachedEntities.AnyAsync(u => u.Code == input.Code && u.Name == input.Name);
            if (isExist)
                throw Oops.Oh("已存在相同名称与编号的设备仪器");

            if (string.IsNullOrWhiteSpace(input.Code))
            {
                input.Code = await _generateCodeUtilService.GenerateCode(BusinessType.EquipmentInfo);
            }
            var equipment = input.Adapt<EquipmentInfo>();

            await equipment.InsertAsync();
        }

        /// <summary>
        /// 删除
        /// </summary>
        [HttpPost("equipmentInfo/delete")]
        public async Task Delete(long id)
        {
            var equipment = await _equipmentRep.FirstOrDefaultAsync(u => u.Id == id);
            if (equipment == null)
                throw Oops.Oh("不存在此数据");

            await equipment.DeleteAsync();
        }

        /// <summary>
        /// 编辑
        /// </summary>
        [HttpPost("equipmentInfo/edit")]
        public async Task Edit(EditEquipmentInfoInput input)
        {
            var equipment = await _equipmentRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (equipment == null)
                throw Oops.Oh("不存在此数据！");

            var isExist = await _equipmentRep.DetachedEntities.AnyAsync(u => u.Name == input.Name && u.Code == input.Code && u.Id != input.Id);
            if (isExist)
                throw Oops.Oh("已存在相同名称与编号的设备仪器");

            var equipmentModel = input.Adapt<EquipmentInfo>();

            await equipmentModel.UpdateAsync();
        }

        /// <summary>
        /// 下拉数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("equipmentInfo/selectList")]
        public async Task<List<SelectDto>> SelectList()
        {
            var list = await _equipmentRep.DetachedEntities.Where(s => s.ValidStatus).OrderBy(s => s.Sort).ToListAsync();
            return list.Select(x => new SelectDto
            {
                Value = x.Id,
                Label = x.Name
            }).ToList();
        }

        /// <summary>
        /// 详细信息
        /// </summary>
        [HttpGet("equipmentInfo/detail")]
        public async Task<EquipmentInfoOutput> Detail(long id)
        {
            EquipmentInfo equipmentInfo = await _equipmentRep.DetachedEntities
                                         .Include(x => x.EquipmentCategory)
                                         .Include(x => x.EquipmentFactory)
                                         .Include(x => x.ExperimentStation)
                                         .FirstOrDefaultAsync(u => u.Id == id);
            if (equipmentInfo == null)
                throw Oops.Oh("不存在此数据！");

            EquipmentInfoOutput detail = equipmentInfo.Adapt<EquipmentInfoOutput>();

            return detail;
        }

        /// <summary>
        /// 详细信息
        /// </summary>
        [HttpGet("equipmentInfo/detailByCode")]
        public async Task<EquipmentInfoOutput> DetailByCode(string equipmentCode)
        {
            EquipmentInfo equipmentInfo = await _equipmentRep.DetachedEntities
                                         .Include(x => x.EquipmentCategory)
                                         .Include(x => x.EquipmentFactory)
                                         .Include(x => x.ExperimentStation)
                                         .FirstOrDefaultAsync(u => u.Code == equipmentCode);
            if (equipmentInfo == null)
                throw Oops.Oh("不存在此数据！");

            EquipmentInfoOutput detail = equipmentInfo.Adapt<EquipmentInfoOutput>();

            return detail;
        }

        /// <summary>
        /// 分页数据
        /// </summary>
        [HttpGet("equipmentInfo/page")]
        public async Task<PageResult<EquipmentInfoOutput>> QueryPage([FromQuery] EquipmentInfoPageInput input)
        {
            var code = !string.IsNullOrEmpty(input.Code?.Trim());
            var name = !string.IsNullOrEmpty(input.SearchValue?.Trim());  

            var equipments = await _equipmentRep.DetachedEntities
                                         .Include(x => x.EquipmentCategory)
                                         .Include(x => x.EquipmentFactory)
                                         .Include(x => x.ExperimentStation)
                                         .Where((code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")))
                                         .Where((name, u => EF.Functions.Like(u.Name, $"%{input.SearchValue.Trim()}%")))
                                         .Where(input.CategoryId.HasValue, u => u.EquipmentCategory.Pids.Contains(input.CategoryId.ToString()) || u.EquipmentCategoryId == input.CategoryId)
                                         .Where(input.EquipmentFactoryId.HasValue, u => u.EquipmentFactoryId == input.EquipmentFactoryId)
                                         .Where(input.ExperimentStationId.HasValue, u => u.ExperimentStationId == input.ExperimentStationId)
                                         .Where(input.EquipmentStatus.HasValue, u => u.EquipmentStatus == input.EquipmentStatus)
                                         .Where(input.ValidStatus.HasValue, u => u.ValidStatus == input.ValidStatus)
                                         .Where(input.BuyTimeStart.HasValue, u => u.BuyTime >= input.BuyTimeStart.Value.Date && u.BuyTime <= input.BuyTimeEnd.Value.AddDays(1).AddSeconds(-1))
                                         .OrderBy(u => u.Sort)
                                         .Select(u => new EquipmentInfoOutput
                                         {
                                             Id = u.Id,
                                             Code = u.Code,
                                             Name = u.Name,
                                             EquipmentCategoryId = u.EquipmentCategoryId,
                                             EquipmentCategoryName = u.EquipmentCategory.Name,
                                             Specification = u.Specification,
                                             Degree = u.Degree,
                                             EquipmentImage = u.EquipmentImage,
                                             ProduceTime = u.ProduceTime,
                                             BuyTime = u.BuyTime,
                                             EquipmentFactoryId = u.EquipmentFactoryId,
                                             EquipmentFactoryName = u.EquipmentFactory.Name,
                                             ExperimentStationId = u.ExperimentStationId,
                                             ExperimentStationName = u.ExperimentStation.Name,
                                             Remark = u.Remark,
                                             EquipmentStatus = u.EquipmentStatus,
                                             ValidStatus = u.ValidStatus,
                                             Sort = u.Sort,
                                         }).ToADPagedListAsync(input.PageNo, input.PageSize);

            return equipments;
        }
    }
}
